package FD4RDF;

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.util.FileManager;

public class ReadRDFs {

  //The input file in RDF datasets
  static final String inputFile = "./src/FD4RDF/MusicArtist.rdf";
  public static FileOutputStream Output;
  public static PrintStream file;
  public static String res;
  public static ArrayList<String> Attri=new ArrayList<String>();
  public static ArrayList<String []> Tripple=new ArrayList<String []>();
  private static ArrayList<String []> R=new ArrayList<String []>();
  
  public static ArrayList<String []> Temp=new ArrayList<String []>();
  public static ArrayList<String> Temp1=new ArrayList<String>();

	void FastFD() {
		Get_Tripple();
		Process_Tripple();
		System.out.println("\nLa resutat de la recuperation de données : \n");
		for(int i=0;i<R.size();i++)
		{
			String [] r=R.get(i);
			System.out.println(" | "+r[0]+" | "+r[1]+" | "+r[2]+" | "+r[3]+" | "+r[4]+" | "+r[5]);
		}
	}
	public static void Get_Tripple()
	{		
		try{
			
			InputStream in = FileManager.get().open(inputFile);			
			
			// Create an empty in-memory model and populate it from the graph
			Model model = ModelFactory.createDefaultModel();
			
			model.read(in,null); // null base URI, since model URIs are absolute
			in.close();									  	       	
			
			String stringQuery1 = "SELECT DISTINCT ?o WHERE { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?o }";		
			
			Query queryRes2 = QueryFactory.create(stringQuery1 );
			QueryExecution qeRes = QueryExecutionFactory.create(queryRes2, model);  
			
			ArrayList<String> resources = new ArrayList<String>();
			
			// Execute the query and obtain results
			ResultSet resultsRes = qeRes.execSelect();
			
			while (resultsRes.hasNext())
			{		         
		         resources.add(resultsRes.next().toString().replace("( ?o = ","").replace(")", ""));		         
			}

			for (int i=0;i<resources.size();i++)
			{
				System.out.println((i+1) + ". " +resources.get(i));
			}
			
			System.out.println("Choisir la Resource préférée : ");
			Scanner read = new Scanner(System.in);
			String Res = read.nextLine();
					
			Timer t = new Timer();
      t.start();

		  if ((Integer.parseInt(Res) <= resources.size()) || (Integer.parseInt(Res) <= 0))
		  {
				String queryString = "DESCRIBE ?x " +
				"WHERE {?x a "+ resources.get(Integer.parseInt(Res)-1) +"; ?z ?y. " +
				"FILTER (?z=<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>)}";		
				
				Query query = QueryFactory.create(queryString);
				QueryExecution qe = QueryExecutionFactory.create(query, model);
								
				// Execute the query and obtain results
				Model m = qe.execDescribe();
				//list the statements in the graph
			    StmtIterator iter = m.listStatements();
		  		while (iter.hasNext()) {
		  			 	String [] tripple=new String[3];
		  			 	Statement stmt      = iter.nextStatement();      // get next statement
		  	       Resource  subject   = stmt.getSubject();   			// get the subject
		  	       Property  predicate = stmt.getPredicate(); 			// get the predicate
		  	       RDFNode   object    = stmt.getObject();    			// get the object    
		  	            
               if (object instanceof Resource) {
                  tripple[0]=subject.toString();
                  tripple[1]=predicate.toString();
                  tripple[2]=object.toString();
                  Tripple.add(tripple);
                  Check_Add(tripple[1]);
               } else {
                   // object is a literal
                  tripple[0]=subject.toString();
                  tripple[1]=predicate.toString();
                  tripple[2]=object.toString();
                  Check_Add(tripple[1]);
                  Tripple.add(tripple);
               }                                                            	
		  		 }		
								
			// Output query results	
			
			// Important - free up resources used running the query
			qe.close();
			
			for (int i=0; i < 80; i++){ System.out.print(".");}
			t.end();
			System.out.println("\nLe temps d'execution de la recuperation des triplets : " + t.duration() + " ms\n");
      }
      else
      System.out.println("Input Erreur..!");
		}
   catch( IOException e )  // catch any errors
		{
		   System.out.println( "There was an IOException error!" );
    }		
	}		   
	
	public static void Process_Tripple() //Tach Data
	{
		Timer tm = new Timer();
	    tm.start();
		int count=1;
		while(Tripple.size()!=0)
		{
			for(int i=0;i<count;i++)
			{
				if(Temp.size()==0)
				{
					Temp.add(Tripple.get(0));
					Tripple.remove(0);
					count=count+1;
				}
				else
					if(Tripple.size()!=0)
					{
				if(Temp.get(0)[0].equals(Tripple.get(0)[0]))
				{
					Temp.add(Tripple.get(0));
					Tripple.remove(0);
					count=count+1;
				}
				}
			}
			
		Add_R();
		Temp.clear();		
		}
		
		for (int i=0; i < 80; i++){ System.out.print(".");}
		tm.end();
		System.out.println("\nLe temps d'execution de la processus des triplets : " + tm.duration() + " ms\n");
	}
   
	public static void Add_R()
	{
		int pos=0;
		String [] ins_R=new String[Attri.size()+1];
		String [] init=Temp.get(0);
		ins_R[0]=init[0];
		for(int i=0;i<Temp.size();i++)
		{
			String [] tripple=Temp.get(i);
			for(int j=0;j<Attri.size();j++)
			{
				if(tripple[1].equals(Attri.get(j)))
				{
					if(ins_R[j+1]==null)
					{
					
					ins_R[j+1]=tripple[2];
					}
					else
					{
						Temp1.add(tripple[2]);
						pos=j+1;
					}
				}
			}
		}
		R.add(ins_R);
		if(Temp1.size()!=0)
		{
			for(int k=0;k<Temp1.size();k++)
			{
				String [] r=new String[Attri.size()+1];
				for(int l=0;l<ins_R.length;l++)
				{
					r[l]=ins_R[l];
				}
			String data=Temp1.get(k);
			r[pos]=data;
			R.add(r);
			}
		}
		Temp1.clear();
	}
   
	public static void Check_Add(String valeur)
	{
			int noitifi=0;
			for(int i=0;i<Attri.size();i++)
			{
				String GET=Attri.get(i);
				if(GET.trim().equals(valeur))
				{
					Attri.set(i, valeur);
					noitifi=1;
				}
			}
		if(noitifi==0)
			Attri.add(valeur.trim());
	}
}
